"""
Java请求处理器
处理来自Java端的各种请求
"""

import json
import time
import logging
from pathlib import Path
from typing import Dict, Any, Optional
from dataclasses import asdict

from .protocol import (
    IntegrationRequest, IntegrationResponse, IntegrationProtocol,
    ActionType, PresentationConfig, SlideConfig, AnimationConfig
)

# 尝试导入MD2PPT核心模块
try:
    from ..parser.md_parser import MarkdownParser
    from ..converter.ppt_builder import PPTBuilder
    from ..styling.theme_manager import ThemeManager
    MD2PPT_AVAILABLE = True
except ImportError:
    MD2PPT_AVAILABLE = False
    logging.warning("MD2PPT核心模块不可用，将使用简化实现")

class RequestHandler:
    """Java请求处理器"""
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        self.temp_dir = Path("temp_communication")
        self.temp_dir.mkdir(exist_ok=True)
    
    def handle_request(self, request_file: Path) -> IntegrationResponse:
        """处理Java请求"""
        start_time = time.time()
        
        try:
            # 读取请求文件
            request = self._read_request_file(request_file)
            if not request:
                return IntegrationProtocol.create_error_response("无法读取请求文件")
            
            # 验证请求格式
            if not request.validate():
                return IntegrationProtocol.create_error_response("请求格式无效")
            
            # 验证选项
            option_errors = IntegrationProtocol.validate_options(request.options)
            if option_errors:
                return IntegrationProtocol.create_error_response(
                    f"选项验证失败: {'; '.join(option_errors)}"
                )
            
            # 处理请求
            response = self._dispatch_request(request)
            response.processing_time = time.time() - start_time
            response.request_id = request.request_id
            
            return response
            
        except Exception as e:
            self.logger.error(f"请求处理失败: {e}", exc_info=True)
            return IntegrationProtocol.create_error_response(
                f"处理异常: {str(e)}",
                processing_time=time.time() - start_time
            )
    
    def _read_request_file(self, request_file: Path) -> Optional[IntegrationRequest]:
        """读取请求文件"""
        try:
            with open(request_file, 'r', encoding='utf-8') as f:
                data = json.load(f)
            
            return IntegrationRequest(
                action=data['action'],
                input_path=data['inputPath'],
                options=data['options'],
                request_id=data['requestId']
            )
        except Exception as e:
            self.logger.error(f"读取请求文件失败: {e}")
            return None
    
    def _dispatch_request(self, request: IntegrationRequest) -> IntegrationResponse:
        """分发请求到具体处理方法"""
        action = request.action
        
        if action == ActionType.PREPROCESS.value:
            return self._handle_preprocess(request)
        elif action == ActionType.GENERATE_BASE.value:
            return self._handle_generate_base(request)
        elif action == ActionType.VALIDATE.value:
            return self._handle_validate(request)
        elif action == ActionType.ENHANCE_ANIMATIONS.value:
            return self._handle_enhance_animations(request)
        else:
            return IntegrationProtocol.create_error_response(f"不支持的操作: {action}")
    
    def _handle_preprocess(self, request: IntegrationRequest) -> IntegrationResponse:
        """处理Markdown预处理请求"""
        input_path = Path(request.input_path)
        options = IntegrationProtocol.merge_with_defaults(request.options)
        
        if not input_path.exists():
            return IntegrationProtocol.create_error_response(f"输入文件不存在: {input_path}")
        
        try:
            if MD2PPT_AVAILABLE:
                # 使用完整的MD2PPT解析器
                parser = MarkdownParser()
                parsed_data = parser.parse_file(input_path)
                
                # 转换为标准格式
                slides = self._convert_parsed_data_to_slides(parsed_data, options)
            else:
                # 简化实现
                slides = self._simple_markdown_parse(input_path, options)
            
            # 生成配置文件
            config_path = self._generate_config_file(slides, options, request.request_id)
            
            return IntegrationProtocol.create_success_response({
                "config_path": str(config_path),
                "slide_count": len(slides),
                "input_format": "markdown",
                "theme": options.get('theme', 'default')
            }, "Markdown预处理完成")
            
        except Exception as e:
            return IntegrationProtocol.create_error_response(f"预处理失败: {str(e)}")
    
    def _handle_generate_base(self, request: IntegrationRequest) -> IntegrationResponse:
        """处理基础PPT生成请求"""
        config_path = Path(request.input_path)
        options = IntegrationProtocol.merge_with_defaults(request.options)
        
        if not config_path.exists():
            return IntegrationProtocol.create_error_response(f"配置文件不存在: {config_path}")
        
        try:
            # 读取配置
            with open(config_path, 'r', encoding='utf-8') as f:
                config_data = json.load(f)
            
            if MD2PPT_AVAILABLE:
                # 使用完整的PPT构建器
                builder = PPTBuilder()
                output_path = Path(options.get('output_path', 'output.pptx'))
                
                presentation = builder.build_from_config(config_data)
                builder.save(presentation, output_path)
                
                file_size = output_path.stat().st_size if output_path.exists() else 0
            else:
                # 简化实现 - 创建基础PPTX文件
                output_path = self._create_basic_pptx(config_data, options)
                file_size = output_path.stat().st_size if output_path.exists() else 0
            
            return IntegrationProtocol.create_success_response({
                "output_path": str(output_path),
                "file_size": file_size,
                "slide_count": len(config_data.get('slides', [])),
                "animations_supported": MD2PPT_AVAILABLE
            }, "基础PPT生成完成")
            
        except Exception as e:
            return IntegrationProtocol.create_error_response(f"基础PPT生成失败: {str(e)}")
    
    def _handle_validate(self, request: IntegrationRequest) -> IntegrationResponse:
        """处理配置验证请求"""
        input_path = Path(request.input_path)
        
        if not input_path.exists():
            return IntegrationProtocol.create_error_response(f"文件不存在: {input_path}")
        
        try:
            validation_results = {}
            warnings = []
            
            if input_path.suffix.lower() == '.json':
                # 验证JSON配置文件
                with open(input_path, 'r', encoding='utf-8') as f:
                    config_data = json.load(f)
                
                validation_results = self._validate_config_structure(config_data)
                if not validation_results['valid']:
                    warnings.extend(validation_results['errors'])
            
            elif input_path.suffix.lower() in ['.md', '.markdown']:
                # 验证Markdown文件
                validation_results = self._validate_markdown_file(input_path)
            
            else:
                return IntegrationProtocol.create_error_response(f"不支持的文件类型: {input_path.suffix}")
            
            response = IntegrationProtocol.create_success_response(
                validation_results, "文件验证完成"
            )
            response.warnings = warnings
            
            return response
            
        except Exception as e:
            return IntegrationProtocol.create_error_response(f"验证失败: {str(e)}")
    
    def _handle_enhance_animations(self, request: IntegrationRequest) -> IntegrationResponse:
        """处理动画增强请求"""
        # 这个功能主要由Java端Aspose实现，Python端提供配置支持
        return IntegrationProtocol.create_success_response({
            "enhancement_available": False,
            "recommendation": "使用Java Aspose.Slides获得最佳动画支持"
        }, "动画增强功能需要Java端Aspose.Slides支持")
    
    def _simple_markdown_parse(self, md_path: Path, options: Dict[str, Any]) -> list:
        """简化的Markdown解析（当MD2PPT不可用时）"""
        with open(md_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        # 简单的标题解析
        lines = content.split('\n')
        slides = []
        current_slide = None
        slide_index = 0
        
        for line in lines:
            line = line.strip()
            if line.startswith('# '):
                # 新幻灯片
                if current_slide:
                    slides.append(current_slide)
                
                slide_index += 1
                current_slide = {
                    'index': slide_index,
                    'title': line[2:],
                    'content': [],
                    'animations': []
                }
            elif line and current_slide:
                # 添加内容
                current_slide['content'].append({
                    'type': 'text',
                    'data': {'text': line},
                    'position': {'x': 100, 'y': 200 + len(current_slide['content']) * 50, 'width': 800, 'height': 40}
                })
        
        if current_slide:
            slides.append(current_slide)
        
        return slides
    
    def _convert_parsed_data_to_slides(self, parsed_data: Any, options: Dict[str, Any]) -> list:
        """转换解析数据为幻灯片格式"""
        # 这里需要根据实际的MD2PPT解析器输出格式来实现
        # 现在返回示例格式
        return [
            {
                'index': 1,
                'title': '示例幻灯片',
                'content': [
                    {
                        'type': 'text',
                        'data': {'text': '这是从MD2PPT解析的内容'},
                        'position': {'x': 100, 'y': 200, 'width': 800, 'height': 100}
                    }
                ],
                'animations': []
            }
        ]
    
    def _generate_config_file(self, slides: list, options: Dict[str, Any], request_id: str) -> Path:
        """生成Java端期望的配置文件"""
        config = {
            "metadata": {
                "title": options.get('title', 'MD2PPT生成的演示文稿'),
                "author": "MD2PPT Python-Java集成",
                "version": "1.0.0",
                "created": time.strftime("%Y-%m-%d")
            },
            "settings": {
                "theme": options.get('theme', 'default'),
                "quality": options.get('quality', 'normal').upper(),
                "timeout_seconds": options.get('timeout_seconds', 300),
                "animation_engine": options.get('animation_engine', 'aspose').upper() + '_JAVA',
                "fallback_engine": "PYTHON_PPTX"
            },
            "slides": slides
        }
        
        config_path = self.temp_dir / f"{request_id}_config.json"
        with open(config_path, 'w', encoding='utf-8') as f:
            json.dump(config, f, ensure_ascii=False, indent=2)
        
        return config_path
    
    def _create_basic_pptx(self, config_data: Dict[str, Any], options: Dict[str, Any]) -> Path:
        """创建基础PPTX文件（简化实现）"""
        # 使用python-pptx创建基础演示文稿
        try:
            from pptx import Presentation
            from pptx.util import Inches
            
            prs = Presentation()
            
            for slide_config in config_data.get('slides', []):
                slide_layout = prs.slide_layouts[1]  # Title and Content
                slide = prs.slides.add_slide(slide_layout)
                
                # 设置标题
                title = slide.shapes.title
                title.text = slide_config.get('title', '无标题')
                
                # 添加内容
                if slide_config.get('content'):
                    content_shape = slide.placeholders[1]
                    text_frame = content_shape.text_frame
                    
                    for content_item in slide_config['content']:
                        if content_item.get('type') == 'text':
                            p = text_frame.paragraphs[0] if len(text_frame.paragraphs) == 1 and not text_frame.paragraphs[0].text else text_frame.add_paragraph()
                            p.text = content_item.get('data', {}).get('text', '')
            
            output_path = Path(options.get('output_path', self.temp_dir / 'basic_output.pptx'))
            prs.save(str(output_path))
            
            return output_path
            
        except ImportError:
            # 如果python-pptx也不可用，创建一个占位文件
            output_path = Path(options.get('output_path', self.temp_dir / 'placeholder.txt'))
            with open(output_path, 'w') as f:
                f.write("基础PPT生成完成，但需要python-pptx库支持")
            return output_path
    
    def _validate_config_structure(self, config_data: Dict[str, Any]) -> Dict[str, Any]:
        """验证配置文件结构"""
        errors = []
        warnings = []
        
        # 检查必需字段
        required_fields = ['metadata', 'settings', 'slides']
        for field in required_fields:
            if field not in config_data:
                errors.append(f"缺少必需字段: {field}")
        
        # 检查slides数组
        if 'slides' in config_data:
            slides = config_data['slides']
            if not isinstance(slides, list):
                errors.append("slides必须是数组")
            elif len(slides) == 0:
                warnings.append("没有定义幻灯片")
            else:
                for i, slide in enumerate(slides):
                    if not isinstance(slide, dict):
                        errors.append(f"幻灯片 {i} 格式错误")
                    elif 'title' not in slide:
                        warnings.append(f"幻灯片 {i} 缺少标题")
        
        return {
            'valid': len(errors) == 0,
            'errors': errors,
            'warnings': warnings,
            'slide_count': len(config_data.get('slides', []))
        }
    
    def _validate_markdown_file(self, md_path: Path) -> Dict[str, Any]:
        """验证Markdown文件"""
        with open(md_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        lines = content.split('\n')
        headers = [line for line in lines if line.strip().startswith('#')]
        
        return {
            'valid': True,
            'file_size': md_path.stat().st_size,
            'line_count': len(lines),
            'header_count': len(headers),
            'estimated_slides': len([h for h in headers if h.startswith('# ')])
        }